package com.ssy.lingxi.member.merchant.serviceimpl.feign;

import com.ssy.lingxi.common.constant.basic.UserLoginSourceEnum;
import com.ssy.lingxi.common.constant.member.MemberStatusEnum;
import com.ssy.lingxi.common.constant.member.MemberTypeEnum;
import com.ssy.lingxi.common.constant.member.RoleTypeEnum;
import com.ssy.lingxi.common.response.PageData;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.common.utils.CollectionPageUtil;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignRelationVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignSubordinateMemberVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.request.MemberFeignUserIdVO;
import com.ssy.lingxi.member.merchant.api.model.vo.inner.response.*;
import com.ssy.lingxi.member.merchant.entity.MemberDO;
import com.ssy.lingxi.member.merchant.entity.MemberRelationDO;
import com.ssy.lingxi.member.merchant.entity.MemberUserDO;
import com.ssy.lingxi.member.merchant.entity.RoleDO;
import com.ssy.lingxi.member.merchant.model.bo.AuthBO;
import com.ssy.lingxi.member.merchant.model.constant.MemberValidateStatusEnum;
import com.ssy.lingxi.member.merchant.repository.MemberRelationRepository;
import com.ssy.lingxi.member.merchant.repository.MemberUserRepository;
import com.ssy.lingxi.member.merchant.service.base.IBaseMemberClassificationService;
import com.ssy.lingxi.member.merchant.service.feign.IMemberDetailFeignService;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.JoinType;
import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 会员、用户信息相关内部Feign服务接口实现类
 * @author 万宁
 * @version 2.0.0
 * @date 2021-06-03
 */
@Service
public class MemberDetailFeignServiceImpl implements IMemberDetailFeignService {
    @Resource
    private MemberRelationRepository relationRepository;

    @Resource
    private MemberUserRepository memberUserRepository;

    @Resource
    private IBaseMemberClassificationService baseMemberClassificationService;

    /**
     * 查询用户Web端菜单权限Url列表
     *
     * @param userId 用户Id
     * @return 查询结果
     */
    @Override
    public Wrapper<List<String>> getUserWebAuthUrls(Long userId) {
        MemberUserDO userDO = memberUserRepository.findById(userId).orElse(null);
        if (userDO == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
        }

        return Wrapper.success(userDO.getUserAuth().getAuth().stream().filter(authBO -> authBO.getSource().equals(UserLoginSourceEnum.BUSINESS_WEB.getCode())).map(AuthBO::getUrl).collect(Collectors.toList()));
    }

    /**
     * 根据会员id查询用户
     * @param memberIds 会员id
     * @return 查询结果
     */
    @Override
    public Wrapper<List<MemberFeignMsgByMemberIdVO>> getUserByMemberIds(List<Long> memberIds) {

        Specification<MemberUserDO> specification = (Specification<MemberUserDO>) (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(cb.and(root.get("member").as(MemberDO.class).in(memberIds)));

            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        };

        List<MemberUserDO> memberUserDOList = memberUserRepository.findAll(specification);

        List<MemberFeignMsgByMemberIdVO> resultList = memberUserDOList.stream().map(memberUserDO -> {
            MemberFeignMsgByMemberIdVO memberFeignMsgByMemberIdVO = new MemberFeignMsgByMemberIdVO();
            memberFeignMsgByMemberIdVO.setMemberId(memberUserDO.getMember().getId());
            memberFeignMsgByMemberIdVO.setUserId(memberUserDO.getId());
            return memberFeignMsgByMemberIdVO;
        }).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    /**
     * 根据角色id查询用户
     * @param roleIds 角色id
     * @return 查询结果
     */
    @Override
    public Wrapper<List<MemberFeignMsgByRoleIdVO>> getUserByRoleIds(List<Long> roleIds) {
        Specification<MemberUserDO> specification = (Specification<MemberUserDO>) (root, query, cb) -> {
            List<Predicate> list = new ArrayList<>();

            Join<MemberUserDO, MemberDO> memberJoin = root.join("member", JoinType.LEFT);
            Join<MemberDO, RoleDO> roleJoin = memberJoin.join("roles", JoinType.LEFT);
            list.add(cb.and(roleJoin.get("id").as(Long.class).in(roleIds)));

            Predicate[] p = new Predicate[list.size()];
            return cb.and(list.toArray(p));
        };

        List<MemberUserDO> memberUserDOList = memberUserRepository.findAll(specification);

        List<MemberFeignMsgByRoleIdVO> resultList = memberUserDOList.stream()
                .flatMap(memberUserDO -> memberUserDO.getMember().getRoles().stream()
                        .filter(roleDO -> roleIds.contains(roleDO.getId()))
                        .map(roleDO -> {
                            MemberFeignMsgByRoleIdVO memberFeignMsgByRoleIdVO = new MemberFeignMsgByRoleIdVO();
                            memberFeignMsgByRoleIdVO.setMemberId(memberUserDO.getMember().getId());
                            memberFeignMsgByRoleIdVO.setRoleId(roleDO.getId());
                            memberFeignMsgByRoleIdVO.setUserId(memberUserDO.getId());
                            return memberFeignMsgByRoleIdVO;
                        })
                ).collect(Collectors.toList());

        return Wrapper.success(resultList);
    }

    /**
     * 结算能力 - 查询入库分类信息中，主营品类及结算方式
     *
     * @param relationVO 接口参数
     * @return 查询结果，如无配置返回空列表
     */
    @Override
    public Wrapper<List<MemberCategoryFeignVO>> findMemberBusinessCategories(MemberFeignRelationVO relationVO) {
        MemberRelationDO relationDO = relationRepository.findFirstByMemberIdAndRoleIdAndSubMemberIdAndSubRoleId(relationVO.getUpperMemberId(), relationVO.getUpperRoleId(), relationVO.getSubMemberId(), relationVO.getSubRoleId());
        if(relationDO == null || !relationDO.getVerified().equals(MemberValidateStatusEnum.VERIFY_PASSED.getCode())) {
            return Wrapper.success(new ArrayList<>());
        }

        return Wrapper.success(baseMemberClassificationService.findMemberBusinessCategories(relationDO));
    }

    /**
     * 根据用户Id查询用户信息
     *
     * @param idVO 接口参数
     * @return 查询结果
     */
    @Override
    public Wrapper<MemberFeignUserDetailVO> findMemberUser(MemberFeignUserIdVO idVO) {
        MemberUserDO memberUser = memberUserRepository.findById(idVO.getUserId()).orElse(null);
        if(memberUser == null) {
            return Wrapper.fail(ResponseCode.MC_MS_MEMBER_USER_DOES_NOT_EXIST);
        }

        MemberFeignUserDetailVO detailVO = new MemberFeignUserDetailVO();
        detailVO.setUserId(memberUser.getId());
        detailVO.setUserName(memberUser.getName());
        detailVO.setJobTitle(memberUser.getOrg() == null ? "" : memberUser.getOrg().getTitle());
        detailVO.setJobTitle(memberUser.getJobTitle());

        return Wrapper.success(detailVO);
    }

    /**
     * 根据会员id和角色id，查询会员角色为服务提供者的下级会员列表
     * @param memberVO 上级会员信息
     * @return 查询结果
     */
    @Override
    public Wrapper<List<MemberManageQueryVO>> subordinateMemberList(MemberFeignSubordinateMemberVO memberVO) {
        Specification<MemberRelationDO> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> list = new ArrayList<>();
            list.add(criteriaBuilder.equal(root.get("memberId").as(Long.class), memberVO.getMemberId()));
            list.add(criteriaBuilder.equal(root.get("roleId").as(Long.class), memberVO.getMemberRoleId()));
            list.add(criteriaBuilder.equal(root.get("verified").as(Integer.class), MemberValidateStatusEnum.VERIFY_PASSED.getCode()));
            list.add(criteriaBuilder.equal(root.get("status").as(Integer.class), MemberStatusEnum.NORMAL.getCode()));
            Join<Object, Object> subRoleJoin = root.join("subRole", JoinType.LEFT);
            list.add(criteriaBuilder.equal(subRoleJoin.get("roleType").get("typeEnum").as(Integer.class), RoleTypeEnum.SERVICE_PROVIDER.getCode()));

            Predicate[] p = new Predicate[list.size()];
            return criteriaBuilder.and(list.toArray(p));
        };

        List<MemberRelationDO> relationDOList = relationRepository.findAll(specification, Sort.by("id").ascending());
        return Wrapper.success(relationDOList.stream().map(p -> {
            MemberManageQueryVO queryVO = new MemberManageQueryVO();
            queryVO.setId(p.getId());
            queryVO.setMemberId(p.getSubMemberId());
            queryVO.setName(p.getSubMember().getName());
            queryVO.setRoleId(p.getSubRoleId());
            queryVO.setRoleName(p.getSubRole().getRoleName());
            queryVO.setMemberTypeName(MemberTypeEnum.getCodeMessage(p.getSubRole().getMemberType().getTypeEnum()));
            queryVO.setLevel(p.getLevelRight().getLevel());
            queryVO.setLevelTag(p.getLevelRight().getLevelTag());
            return queryVO;
        }).collect(Collectors.toList()));
    }
}
